﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

//对称加密
namespace Com.Lancetinc.Evs.Helpers
{
    public class CipherUtils
    {
        //默认密钥向量 AGS-2015
        private static byte[] _rgbIV = { 0x41, 0x47, 0x53, 0x2D, 0x32, 0x30, 0x31, 0x35 };

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="plainText">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥,要求为8位</param>
        /// <returns>加密成功返回加密后的字符串，失败返回源串</returns>
        public static string Encrypt(string plainText, string encryptKey)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
                byte[] rgbIV = _rgbIV;
                byte[] inputByteArray = Encoding.UTF8.GetBytes(plainText);
                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            catch
            {
                return plainText;
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptedText">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
        /// <returns>解密成功返回解密后的字符串，失败返源串</returns>
        public static string Decrypt(string decryptedText, string decryptKey)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 8));
                byte[] rgbIV = _rgbIV;
                byte[] inputByteArray = Convert.FromBase64String(decryptedText);
                DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Encoding.UTF8.GetString(mStream.ToArray());
            }
            catch
            {
                return decryptedText;
            }
        }

        public static string GetRandomString(int length)
        {
            const string CHARS = @"0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
            Random rand = new Random(Environment.TickCount);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(CHARS[rand.Next(CHARS.Length)]);
            }
            return sb.ToString();
        }

        #region Rc4

        public static string Rc4Encode(string input, string key)
        {
            var rc4 = new RC4(Encoding.UTF8.GetBytes(key));
            var inputByteArray = Encoding.UTF8.GetBytes(input);
            var rc4Result = rc4.Parse(inputByteArray);
            return Convert.ToBase64String(rc4Result);
        }

        public static string Rc4Decode(string input, string key)
        {
            var inputByteArray = Convert.FromBase64String(input);
            var rc4 = new RC4(Encoding.UTF8.GetBytes(key));
            var rc4Result = rc4.Parse(inputByteArray);
            return Encoding.UTF8.GetString(rc4Result);
        }

        private class RC4
        {
            private readonly int[] Table;
            private int i;
            private int j;

            public RC4(byte[] key)
            {
                Table = new int[256];

                Init(key);
            }

            private void Init(byte[] key)
            {
                var k = key.Length;
                i = 0;
                while (i < 256)
                {
                    Table[i] = i;
                    i++;
                }

                i = 0;
                j = 0;
                while (i < 0x0100)
                {
                    j = (j + Table[i] + key[i % k]) % 256;
                    Swap(i, j);
                    i++;
                }

                i = 0;
                j = 0;
            }

            private void Swap(int a, int b)
            {
                var k = Table[a];
                Table[a] = Table[b];
                Table[b] = k;
            }

            public byte[] Parse(byte[] bytes)
            {
                var result = new byte[bytes.Length];
                var pos = 0;

                foreach (var b in bytes)
                {
                    i = (i + 1) % 256;
                    j = (j + Table[i]) % 256;
                    Swap(i, j);
                    var k = (Table[i] + Table[j]) % 256;
                    result[pos++] = (byte)(b ^ Table[k]);
                }

                return result;
            }
        }

        #endregion
    }
}
